﻿using System;

using NUnit.Framework;

using MVCBootstrap.MongoDB;
using MVCBootstrap.MongoDB.Web.Security;
using System.Configuration;
using System.Web.Security;
using MongoDB.Driver;
using System.Web.Mvc;
using System.Threading;

namespace MVCBootstrap.Tests.MongoDB {

	[TestFixture]
	public class UserTests {
		private static MongoDBMembershipProvider provider;
		private const String server = "mongodb://localhost";
		private const String database = "mvcbootstraptest";

		#region Initialization and cleanup
		[TestFixtureSetUp]
		public static void TestInitialize() {
			DependencyResolver.SetResolver(new TestResolver());
			provider = new MongoDBMembershipProvider();
			provider.Initialize("MongoProvider", MembershipTestHelper.GetSettings("MongoProvider"));
		}

		[TestFixtureTearDown]
		public static void TestCleanup() {
			// Let's clear the database!
			new MongoClient(server).GetServer().GetDatabase(database).Drop();
		}
		#endregion

		[Test]
		public void CreateAndGetTest() {
			MembershipCreateStatus status;
			provider.CreateUser("Steen F. Tøttrup", "123456", "TEST@test.com", String.Empty, String.Empty, true, null, out status);
			Assert.AreEqual(MembershipCreateStatus.Success, status);

			MembershipUser user = provider.GetUser("STEEN f. Tøttrup", false);
			Assert.NotNull(user);

			String username = provider.GetUserNameByEmail("test@TEST.com");
			Assert.AreEqual(user.UserName, username);
		}

		[Test]
		public void DuplicateName() {
			MembershipCreateStatus status;
			provider.CreateUser("王冰清", "123456", "test2@test.com", String.Empty, String.Empty, true, null, out status);
			Assert.AreEqual(MembershipCreateStatus.Success, status);

			MembershipUser user = provider.GetUser("王冰清", false);
			Assert.NotNull(user);

			provider.CreateUser("王冰清", "123456", "test3@test.com", String.Empty, String.Empty, true, null, out status);
			Assert.AreEqual(MembershipCreateStatus.DuplicateUserName, status);
		}

		[Test]
		public void DuplicateEmail() {
			MembershipCreateStatus status;
			provider.CreateUser("Name Again", "123456", "test4@test.com", String.Empty, String.Empty, true, null, out status);
			Assert.AreEqual(MembershipCreateStatus.Success, status);

			String username = provider.GetUserNameByEmail("test4@TEST.com");
			Assert.AreEqual("Name Again", username);

			provider.CreateUser("Another Name", "123456", "test4@test.com", String.Empty, String.Empty, true, null, out status);
			Assert.AreEqual(MembershipCreateStatus.DuplicateEmail, status);
		}

		[Test]
		public void LockTest() {
			String username = "lock Test";
			String password = "t4t4t4t";
			String wrongPW = "jrtjrjrt";
			MembershipCreateStatus status;
			provider.CreateUser(username, password, "test99@test.com", String.Empty, String.Empty, true, null, out status);
			Assert.AreEqual(MembershipCreateStatus.Success, status);

			Assert.AreEqual(false, provider.ValidateUser(username, wrongPW));

			Assert.AreEqual(false, provider.ValidateUser(username, wrongPW));

			Assert.AreEqual(false, provider.ValidateUser(username, wrongPW));

			Assert.AreEqual(false, provider.ValidateUser(username, wrongPW));
			MembershipUser user = provider.GetUser(username, false);
			Assert.AreEqual(false, user.IsLockedOut);

			Assert.AreEqual(false, provider.ValidateUser(username, wrongPW));
			user = provider.GetUser(username, false);
			Assert.AreEqual(true, user.IsLockedOut);
			user.UnlockUser();

			Assert.AreEqual(true, provider.ValidateUser(username, password));
		}

		[Test]
		public void LockWindowTest() {
			String username = "Lock Window";
			String password = "t4t4t4t";
			String wrongPW = "jrtjrjrt";
			MembershipCreateStatus status;
			provider.CreateUser(username, password, "test999@test.com", String.Empty, String.Empty, true, null, out status);
			Assert.AreEqual(MembershipCreateStatus.Success, status);

			Assert.AreEqual(false, provider.ValidateUser(username, wrongPW));

			Assert.AreEqual(false, provider.ValidateUser(username, wrongPW));

			Assert.AreEqual(false, provider.ValidateUser(username, wrongPW));

			Assert.AreEqual(false, provider.ValidateUser(username, wrongPW));
			MembershipUser user = provider.GetUser(username, false);
			Assert.AreEqual(false, user.IsLockedOut);

			Thread.Sleep(1000 * 60 * Membership.Provider.PasswordAttemptWindow);

			Assert.AreEqual(false, provider.ValidateUser(username, wrongPW));
			user = provider.GetUser(username, false);
			Assert.AreEqual(false, user.IsLockedOut);
		}
	}
}